
#include "lccc.h"
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct{
    lua_State*L;
    int ref;
}Userdata_t;

static int callback(void*user_data,int signal,int kind,const char*s){
    Userdata_t *u = user_data;
    if(u){
        if(u->L){
            lua_State *L = u->L;
            lua_rawgeti(L,LUA_REGISTRYINDEX,u->ref);
            if(lua_isfunction(L,-1)){
                lua_pushinteger(L,signal);
                lua_pushinteger(L,kind);
                lua_pushstring(L,s);
                lua_call(u->L,3,1);
                int r = lua_tointeger(u->L,-1);
                return r;
            }
        }
    }
    return 0;
}

int lcallback_gc(lua_State*L){
    if(lua_isuserdata(L,1)){
        Userdata_t **u = lua_touserdata(L,1);
        if(u[0]->ref!=LUA_REFNIL){
            luaL_unref(L,LUA_REGISTRYINDEX,u[0]->ref);
        }
    }
    return 0;
}

int Lget_callback_userdata(lua_State*L){
    if(lua_isfunction(L,1)){
        int ref = luaL_ref(L,LUA_REGISTRYINDEX);


        //lua_newtable(L);

        luaL_newmetatable(L,"CallBack");
        lua_pushcfunction(L,lcallback_gc);
        lua_setfield(L,-2,"__gc");


        Userdata_t **u = lua_newuserdata(L,sizeof(Userdata_t*));
        luaL_setmetatable(L,"CallBack");

        *u = malloc(sizeof(**u));
        u[0]->L = L;
        u[0]->ref = ref;
        return 1;
    }
    return 0;
}

int Lget_callback(lua_State*L){
    lua_pushlightuserdata(L,callback);
    return 1;
}


